/*
 * plio.c
 *
 *  Created on: May 2, 2017
 *      Author: yuanjianen
 */

#include "plio.h"
#include "plio_config.h"
#include "plconfig.h"




static void plio_init_input_switch(void);
static void plio_init_output_switch(void);
static void plio_config_sleep_for_input(void);
static void plio_config_sleep_for_output(void);


static void plio_init_input_switch(void) {
	uint8 index;
	const PlioInputConfig *config;
	PlioInputData *iodata;
	uint8 init_value;
	uint8 port;
	uint8 pin;
	
	for(index = 0U; index < plio_input_switch_count; index++) {
		config = &(plio_input_switch_config[index]);
		port = config->port;
		pin = config->pin;
		if(port == INVALID_PORT || pin == INVALID_PIN) {
			continue ;
		}

		iodata = &(plio_input_switch_data[index]);

		init_value =  plio_read_pin(port, pin);
		iodata->input_raw = init_value;
		iodata->input_debounced = init_value;
		iodata->input_hold = init_value;
	}
}


static void plio_init_output_switch(void) {
	uint8 index;
	const PlioOutputConfig *config;
	uint8 port;
	uint8 pin;
	uint8 poweron_output_level;
	uint8 out_value = 0U;

	for(index = 0U; index < plio_output_switch_count; index++) {
		config = &(plio_output_switch_config[index]);
		port = config->port;
		pin = config->pin;
		if(port == INVALID_PORT || pin == INVALID_PIN) {
			continue ;
		}

		poweron_output_level = config->poweron_output_level;
		if(poweron_output_level == OUTPUT_LEVEL_HIGH) {
			out_value = 1U;
		} else if (poweron_output_level == OUTPUT_LEVEL_LOW) {
			out_value = 0U;
		} else {
			out_value = plio_read_pin(port, pin);
		}
		plio_write_pin(port, pin, out_value);
	}
}


static void plio_config_sleep_for_output(void) {
	uint8 index;
	const PlioOutputConfig *config;
	uint8 port;
	uint8 pin;
	uint8 sleep_output_level;

	for(index = 0U; index < plio_output_switch_count; index++) {
		config = &(plio_output_switch_config[index]);
		port = config->port;
		pin = config->pin;
		if(port == INVALID_PORT || pin == INVALID_PIN) {
			continue ;
		}

		sleep_output_level = config->sleep_output_level;
		if(sleep_output_level == OUTPUT_LEVEL_HIGH) {
			plio_write_pin(port, pin, 1U);
		} else if(sleep_output_level == OUTPUT_LEVEL_LOW) {
			plio_write_pin(port, pin, 0U);
		} else {
			/*keep as output, and keep the ouput level*/
		}
	}
}


static void plio_config_sleep_for_input(void) {
	uint8 index;
	const PlioInputConfig *config;

	uint8 port;
	uint8 pin;
	for(index = 0U; index < plio_input_switch_count; index++) {
		config = &(plio_input_switch_config[index]);
		port = config->port;
		pin = config->pin;
		if(port == INVALID_PORT || pin == INVALID_PIN) {
			continue ;
		}
	}
}


void plio_init_io(void) {
	plio_init_input_switch();
	plio_init_output_switch();
}



void plio_enter_sleep(void) {
	plio_config_sleep_for_input();
	plio_config_sleep_for_output();
}

void plio_input_switch_sample_task(void) {
	uint8 index;
	uint8 raw_input;
	const PlioInputConfig *config;
	PlioInputData *iodata;
	PlioHoldeMode hold_mode;
	for(index = 0U; index < plio_input_switch_count; index++) {
		config = &(plio_input_switch_config[index]);
		iodata = &(plio_input_switch_data[index]);
		raw_input = plio_read_pin(config->port, config->pin);
		hold_mode = config->hold_mode;
		if(config->negative) {
			raw_input = !(raw_input);
		}
		if(iodata->input_raw == raw_input) { /*the old sampled data is same as current sampled data*/
			if(hold_mode != HOLD_ON_NONE) {
				if(iodata->input_debounced == raw_input) {
					if(iodata->hold_time < config->hold_time) {
						iodata->hold_time += PLCFG_INPUT_SAMPLE_TASK_TIME;
					} else {
						iodata->input_hold = raw_input;
					}
				} else {
					iodata->hold_time = 0U;
					if(hold_mode == HOLD_ON_HIGH) {
						if(raw_input == 0U) {
							iodata->input_hold = raw_input; /*return back to low at once*/
						}
					} else if(hold_mode == HOLD_ON_LOW) {
						if(raw_input == 1U) {
							iodata->input_hold = raw_input; /*return back to high at once*/
						}
					} else { /*hold on both*/
						/*keep as old value*/
					}
				}
			}
			iodata->input_debounced = raw_input;
		} else {
			iodata->input_raw = raw_input;
		}
	}
}

